﻿using System;

using System.IO;
using System.Diagnostics;
using NougakudoCompanion.Commons;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace NougakudoCompanion.Utils
{
    static internal class ShortcutPathUtility
    {
        /// <summary>
        /// Get local resource root folder. This method use %TEMP% as environment variable.
        /// Example is "C:\".
        /// This method use by Role code only. Because of %TEMP% of environment variable is difference Role instance in IIS. 
        /// </summary>
        /// <returns>Local resource root folder</returns>
        static internal string GetLocalResourceRoot()
        {
            var temp = System.Environment.GetEnvironmentVariable("TEMP");
            return Path.GetPathRoot(temp);
        }

        /// <summary>
        /// Get NougakuDo logging folder.
        /// Example is "C:\NougakuDo".
        /// This method use by Role code only. Because of %TEMP% of environment variable is difference Role instance in IIS. 
        /// </summary>
        /// <returns>NougakuDo logging folder</returns>
        static internal string GetShortcutRoot()
        {
#if (DEBUG)
            // This line is for multi instances debugg on development fabric.
            //Constants.NOUGAKUDO_NAME = RoleEnvironment.CurrentRoleInstance.Id;
#endif
            return Path.Combine(GetLocalResourceRoot(), Constants.NOUGAKUDO_NAME);
        }

        /// <summary>
        /// Create NougakuDo loggin folder, then set permission to System and Administrators and Netowrk Service. 
        /// </summary>
        /// <returns></returns>
        static internal bool CreateShortcutRoot()
        {
            var root = GetShortcutRoot();
            if (Directory.Exists(root))
            {
#if DEBUG
                Logging.Write("Exsists " + root);
#endif
                return true;
            }
            try
            {
                // Set permission
                var ret = PermissionUtility.SetPermission(root);
                if (ret)
                    Logging.Write("Created NougakuDo shortcut root.");
                else
                    Logging.Write("Failed : Create NougakuDo shortcut root.");
                return ret;
            }
            catch (Exception e)
            {
                Logging.Write("Failed :: " + e.Message);
                return false;
            }
        }

        /// <summary>
        /// Create Symbolic link for NougakuDo Companion local resources.
        /// </summary>
        /// <returns></returns>
        static internal bool CreateNougakudoShortcut()
        {
            var root = Path.Combine(GetLocalResourceRoot(), Constants.NOUGAKUDO_NAME);
            var ret = CreateShortcut(root);

            return ret;
        }

        /// <summary>
        /// Create symbolic link.
        /// </summary>
        /// <param name="root">NougakuDo logging folder</param>
        /// <returns></returns>
        static bool CreateShortcut(string root)
        {
            bool ret = false;
            var shortcutFolders = new string[] {Constants.RESOURCE_APPLICATION, Constants.RESOURCE_DOWNLOAD, Constants.RESOURCE_RUNTIME, Constants.RESOURCE_TEMP}; /* Add temp folder */
            var resourceFolders = new string[] { RoleEnvironment.GetLocalResource(Constants.RESOURCE_APPLICATION).RootPath, 
                                         RoleEnvironment.GetLocalResource(Constants.RESOURCE_DOWNLOAD).RootPath,
                                         RoleEnvironment.GetLocalResource(Constants.RESOURCE_RUNTIME).RootPath,
                                         RoleEnvironment.GetLocalResource(Constants.RESOURCE_TEMP).RootPath /* Add temp folder */  };

            try
            {
                for (int i = 0; i < shortcutFolders.Length; i++)
                {
                    var shortcut = Path.Combine(root, shortcutFolders[i]);
                    ret = CreateSymbolicLink(shortcut, resourceFolders[i]);
#if DEBUG
                    Logging.Write("Create symbolic link as " + shortcut);
#endif
                    if (!ret)
                    {
                        return false;
                    }
                }
                Logging.Write("Created shortcut folder as symbolic link");
                return true;
            }
            catch (Exception e)
            {
                Logging.Write("Failed create shortcut folder : " + e.Message);
                return false;
            }
        }

        static bool CreateSymbolicLink(string linkDestination, string linkSource)
        {
            string message = "";
            StreamReader errReader;
            var doubleQuate = "\"";

            var cmdexe = new ProcessStartInfo("cmd.exe");
            cmdexe.WorkingDirectory = System.Environment.CurrentDirectory;
            cmdexe.UseShellExecute = false;
            cmdexe.RedirectStandardError = true;
            var proc = new Process();

            // Delete exsists link folder.
            if (Directory.Exists(linkDestination))
            {
#if DEBUG
                Logging.Write("Delete exsists symbolic link " + linkDestination);
#endif
                cmdexe.Arguments = "/c rd " + doubleQuate + linkDestination + doubleQuate;
                proc.StartInfo = cmdexe;
                proc.Start();
                errReader = proc.StandardError;
                proc.WaitForExit();
                message = errReader.ReadToEnd();
                if (message != "")
                {
                    Logging.Write("Failed delete synmbolic link : " + message);
                    return false;
                }
            }

            // Create synbolic link
            cmdexe.Arguments = "/c mklink /d " +
                               doubleQuate + linkDestination + doubleQuate + " " +
                               doubleQuate + linkSource + doubleQuate;
            Debug.WriteLine(cmdexe.Arguments);

            proc.StartInfo = cmdexe;
            proc.Start();
            errReader = proc.StandardError;

            proc.WaitForExit();

            message = errReader.ReadToEnd();
            if (message != "")
            {
                Logging.Write("Failed create synmbolic link : " + message);
                return false;
            }
            return true;
        }

    }
}